home *** CD-ROM | disk | FTP | other *** search
- Subject: v16i069: Spiff, find approximate differences in files, Part03/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Daniel W Nachbar <daniel@wind.bellcore.com>
- Posting-number: Volume 16, Issue 69
- Archive-name: spiff/part03
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 3 (of 4)."
- # Contents: float.c parse.c spiff.1
- # Wrapped by rsalz@papaya.bbn.com on Fri Nov 11 13:12:26 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'float.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'float.c'\"
- else
- echo shar: Extracting \"'float.c'\" \(13078 characters\)
- sed "s/^X//" >'float.c' <<'END_OF_FILE'
- X/* Copyright (c) 1988 Bellcore
- X** All Rights Reserved
- X** Permission is granted to copy or use this program, EXCEPT that it
- X** may not be sold for profit, the copyright notice must be reproduced
- X** on copies, and credit should be given to Bellcore where it is due.
- X** BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
- X*/
- X
- X
- X#ifndef lint
- Xstatic char rcsid[]= "$Header: float.c,v 1.1 88/09/15 11:33:53 daniel Rel $";
- X#endif
- X
- X#include <ctype.h>
- X#include "misc.h"
- X#include "floatrep.h"
- X#include "float.h"
- X#include "strings.h"
- X
- X#define _F_GETEND(x) (x + (strlen(x)-1))
- X
- X/*
- Xint floatcnt = 0;
- X*/
- X/*
- X** routines to convert strings to our internal floating point form
- X** isfloat just looks at the string
- X** to see if a conversion is reasonable
- X** it does look-ahead on when it sees an 'e' and such.
- X** atocf actually does the conversion.
- X** these two routines could probably be combined
- X*/
- X
- X/*
- X** test to see if the string can reasonably
- X** be interpreted as floating point number
- X** returns 0 if string can't be interpreted as a float
- X** otherwise returns the number of digits that will be used in F_atof
- X*/
- XF_isfloat(str,need_decimal,allow_sign)
- Xchar *str;
- Xint need_decimal; /* if non-zero, require that a decimal point be present
- X otherwise, accept strings like "123" */
- Xint allow_sign; /* if non-zero, allow + or - to set the sign */
- X{
- X int man_length = 0; /* length of the fractional part (mantissa) */
- X int exp_length = 0; /* length of the exponential part */
- X int got_a_digit = 0; /* flag to set if we ever see a digit */
- X
- X /*
- X ** look for an optional leading sign marker
- X */
- X if (allow_sign && ('+' == *str || '-' == *str))
- X {
- X str++; man_length++;
- X }
- X /*
- X ** count up the digits on the left hand side
- X ** of the decimal point
- X */
- X while(isdigit(*str))
- X {
- X got_a_digit = 1;
- X str++; man_length++;
- X }
- X
- X /*
- X ** check for a decimal point
- X */
- X if ('.' == *str)
- X {
- X str++; man_length++;
- X }
- X else
- X {
- X if (need_decimal)
- X {
- X return(0);
- X }
- X }
- X
- X /*
- X ** collect the digits on the right hand
- X ** side of the decimal point
- X */
- X while(isdigit(*str))
- X {
- X got_a_digit = 1;
- X str++; man_length++;
- X }
- X
- X if (!got_a_digit)
- X return(0);
- X
- X /*
- X ** now look ahead for an exponent
- X */
- X if ('e' == *str ||
- X 'E' == *str ||
- X 'd' == *str ||
- X 'D' == *str)
- X {
- X str++; exp_length++;
- X if ('+' == *str || '-' == *str)
- X {
- X str++; exp_length++;
- X }
- X
- X if (!isdigit(*str))
- X {
- X /*
- X ** look ahead went too far,
- X ** so return just the length of the mantissa
- X */
- X return(man_length);
- X }
- X
- X while (isdigit(*str))
- X {
- X str++; exp_length++;
- X }
- X }
- X return(man_length+exp_length); /* return the total length */
- X}
- X
- X/*
- X** routine to convert a string to our internal
- X** floating point representation
- X**
- X** similar to atof()
- X*/
- XF_float
- XF_atof(str,allflag)
- Xchar *str;
- Xint allflag; /* require that exactly all the characters are used */
- X{
- X char *beg = str; /* place holder for beginning of the string */
- X char man[R_MANMAX]; /* temporary location to build the mantissa */
- X int length = 0; /* length of the mantissa so far */
- X int got_a_digit = 0; /* flag to set if we get a non-zero digit */
- X int i;
- X int resexp;
- X
- X F_float res; /* where we build the result */
- X
- X/*
- Xfloatcnt++;
- X*/
- X res = R_makefloat();
- X
- X R_setsign(res,R_POSITIVE);
- X
- X resexp = 0;
- X man[0] = '\0';
- X
- X /*
- X ** check for leading sign
- X */
- X if ('+' == *str)
- X {
- X /*
- X ** sign should already be positive, see above in this
- X ** routine, so just skip the plus sign
- X */
- X str++;
- X }
- X else
- X {
- X if ('-' == *str)
- X {
- X R_setsign(res,R_NEGATIVE);
- X str++;
- X }
- X }
- X
- X /*
- X ** skip any leading zeros
- X */
- X while('0' == *str)
- X {
- X str++;
- X }
- X
- X /*
- X ** now snarf up the digits on the left hand side
- X ** of the decimal point
- X */
- X while(isdigit(*str))
- X {
- X got_a_digit = 1;
- X man[length++] = *str++;
- X man[length] = '\0';
- X resexp++;
- X }
- X
- X /*
- X ** skip the decimal point if there is one
- X */
- X if ('.' == *str)
- X str++;
- X
- X /*
- X ** trim off any leading zeros (on the right hand side)
- X ** if there were no digits in front of the decimal point.
- X */
- X
- X if (!got_a_digit)
- X {
- X while('0' == *str)
- X {
- X str++;
- X resexp--;
- X }
- X }
- X
- X /*
- X ** now snarf up the digits on the right hand side
- X */
- X while(isdigit(*str))
- X {
- X man[length++] = *str++;
- X man[length] = '\0';
- X }
- X
- X if ('e' == *str ||
- X 'E' == *str ||
- X 'd' == *str ||
- X 'D' == *str )
- X {
- X str++;
- X resexp += atoi(str);
- X }
- X
- X if (allflag)
- X {
- X if ('+' == *str ||
- X '-' == *str)
- X {
- X str++;
- X }
- X while (isdigit(*str))
- X {
- X str++;
- X }
- X if ('\0' != *str)
- X {
- X (void) sprintf(Z_err_buf,
- X "didn't use up all of %s in atocf",
- X beg);
- X Z_fatal(Z_err_buf);
- X }
- X }
- X
- X /*
- X ** check for special case of all zeros in the mantissa
- X */
- X for (i=0;i<length;i++)
- X {
- X if (man[i] != '0')
- X {
- X /*
- X ** the mantissa is non-zero, so return it unchanged
- X */
- X S_trimzeros(man);
- X /*
- X ** save a copy of the mantissa
- X */
- X R_setfrac(res,man);
- X R_setexp(res,resexp);
- X return(res);
- X }
- X }
- X
- X /*
- X ** the answer is 0, so . . .
- X */
- X R_setzero(res);
- X return(res);
- X}
- X
- X
- X/*
- X** add s2 to s1
- X*/
- Xstatic
- Xvoid
- X_F_stradd(s1,s2)
- Xchar *s1,*s2;
- X{
- X char *end1 = s1 + (strlen(s1)-1);
- X char *end2 = s2 + (strlen(s2)-1);
- X
- X static char result[R_MANMAX];
- X char *resptr = result+(R_MANMAX-1); /*point to the end of the array */
- X int carry = 0;
- X int tmp,val1,val2;
- X
- X *resptr-- = '\0';
- X
- X while ((end1 >= s1) || ( end2 >= s2))
- X {
- X if (end1 >= s1)
- X {
- X val1 = *end1 - '0';
- X --end1;
- X }
- X else
- X {
- X val1 = 0;
- X }
- X
- X if (end2 >= s2)
- X {
- X val2 = *end2 - '0';
- X --end2;
- X }
- X else
- X {
- X val2 = 0;
- X }
- X
- X tmp = val1 + val2 + carry;
- X if (tmp > 9)
- X {
- X carry = 1;
- X tmp -= 10;
- X }
- X else
- X {
- X carry = 0;
- X }
- X
- X *resptr-- = tmp+'0';
- X }
- X if (carry)
- X {
- X *resptr = '1';
- X }
- X else
- X {
- X resptr++;
- X }
- X (void) strcpy(s1,resptr);
- X return;
- X}
- X
- X/*
- X** add zero(s) onto the end of a string
- X*/
- Xstatic void
- Xaddzeros(ptr,count)
- Xchar *ptr;
- Xint count;
- X{
- X for(;count> 0;count--)
- X {
- X (void) strcat(ptr,"0");
- X }
- X return;
- X}
- X
- X/*
- X** subtract two mantissa strings
- X*/
- XF_float
- XF_floatsub(p1,p2)
- XF_float p1,p2;
- X{
- X static F_float result;
- X static needinit = 1;
- X static char man1[R_MANMAX],man2[R_MANMAX],diff[R_MANMAX];
- X int exp1,exp2;
- X char *diffptr,*big,*small;
- X int man_cmp_val,i,borrow;
- X
- X if (needinit)
- X {
- X result = R_makefloat();
- X needinit = 0;
- X }
- X
- X man1[0] = '\0';
- X man2[0] = '\0';
- X
- X exp1 = R_getexp(p1);
- X exp2 = R_getexp(p2);
- X
- X /*
- X ** line up the mantissas
- X */
- X while (exp1 < exp2)
- X {
- X (void) strcat(man1,"0");
- X exp1++;
- X }
- X
- X while(exp1 > exp2)
- X {
- X (void) strcat(man2,"0");
- X exp2++;
- X }
- X
- X if (exp1 != exp2) /* boiler plate assertion */
- X {
- X Z_fatal("mantissas didn't get lined up properly in floatsub");
- X }
- X
- X (void) strcat(man1,R_getfrac(p1));
- X (void) strcat(man2,R_getfrac(p2));
- X
- X /*
- X ** now that the mantissa are aligned,
- X ** if the strings are the same, return 0
- X */
- X if((man_cmp_val = strcmp(man1,man2)) == 0)
- X {
- X R_setzero(result);
- X return(result);
- X }
- X
- X /*
- X ** pad the shorter string with 0's
- X ** when this loop finishes, both mantissas should
- X ** have the same length
- X */
- X if (strlen(man1)> strlen(man2))
- X {
- X addzeros(man2,strlen(man1)-strlen(man2));
- X }
- X else
- X {
- X if (strlen(man1)<strlen(man2))
- X {
- X addzeros(man1,strlen(man2)-strlen(man1));
- X }
- X }
- X
- X if (strlen(man1) != strlen(man2)) /* pure boilerplate */
- X {
- X Z_fatal("lengths not equal in F_floatsub");
- X }
- X
- X if (man_cmp_val < 0)
- X {
- X big = man2;
- X small = man1;
- X }
- X else
- X {
- X big = man1;
- X small = man2;
- X }
- X
- X /*
- X ** find the difference between the mantissas
- X */
- X for(i=(strlen(big)-1),borrow=0,diff[strlen(big)] = '\0';i>=0;i--)
- X {
- X char from;
- X if (borrow)
- X {
- X if (big[i] == '0')
- X {
- X from = '9';
- X }
- X else
- X {
- X from = big[i]-1;
- X borrow = 0;
- X }
- X }
- X else
- X {
- X if(big[i]<small[i])
- X {
- X from = '9'+1;
- X borrow = 1;
- X }
- X else
- X {
- X from = big[i];
- X }
- X }
- X diff[i] = (from-small[i]) + '0';
- X }
- X
- X /*
- X ** trim the leading zeros on the difference
- X */
- X diffptr = diff;
- X while('0' == *diffptr)
- X {
- X diffptr++;
- X exp1--;
- X }
- X
- X R_setexp(result,exp1); /* exponents are equal at the point */
- X R_setfrac(result,diffptr);
- X R_setsign(result,R_POSITIVE);
- X return(result);
- X}
- X
- XF_floatcmp(f1,f2)
- XF_float f1,f2;
- X{
- X static char man1[R_MANMAX],man2[R_MANMAX];
- X
- X /*
- X ** special case for zero
- X */
- X if (R_zerofloat(f1))
- X {
- X if (R_zerofloat(f2))
- X {
- X return(0);
- X }
- X else
- X {
- X return(-1);
- X }
- X }
- X else
- X {
- X if (R_zerofloat(f2))
- X {
- X return(1);
- X }
- X }
- X
- X /*
- X ** to reach this point, both numbers must be non zeros
- X */
- X if (R_getexp(f1) < R_getexp(f2))
- X {
- X return(-1);
- X }
- X
- X if (R_getexp(f1) > R_getexp(f2))
- X {
- X return(1);
- X }
- X
- X (void) strcpy(man1,R_getfrac(f1));
- X S_trimzeros(man1);
- X
- X (void) strcpy(man2,R_getfrac(f2));
- X S_trimzeros(man2);
- X return(strcmp(man1,man2));
- X}
- X
- XF_float
- XF_floatmul(f1,f2)
- XF_float f1,f2;
- X{
- X static char prod[R_MANMAX];
- X char *end;
- X int count1 = 0;
- X int count2 = 0;
- X int tmp,len;
- X char *end1;
- X char *end2;
- X static char man1[R_MANMAX],man2[R_MANMAX];
- X char *bigman,*smallman;
- X static F_float result;
- X static int needinit = 1;
- X
- X if (needinit)
- X {
- X result = R_makefloat();
- X needinit = 0;
- X }
- X /*
- X ** special case for a zero result
- X */
- X if (R_zerofloat(f1) || R_zerofloat(f2))
- X {
- X R_setzero(result);
- X return(result);
- X }
- X
- X (void) strcpy(man1,R_getfrac(f1));
- X (void) strcpy(man2,R_getfrac(f2));
- X
- X end1 = _F_GETEND(man1);
- X end2 = _F_GETEND(man2);
- X
- X /*
- X ** decide which number will cause multiplication loop to go
- X ** around the least
- X */
- X while(end1 >= man1)
- X {
- X count1 += *end1 - '0';
- X end1--;
- X }
- X
- X while(end2 >= man2)
- X {
- X count2 += *end2 - '0';
- X end2--;
- X }
- X
- X
- X if (count1 > count2)
- X {
- X bigman = man1;
- X smallman = man2;
- X }
- X else
- X {
- X bigman = man2;
- X smallman = man1;
- X }
- X S_trimzeros(bigman);
- X S_trimzeros(smallman);
- X len = strlen(bigman) + strlen(smallman);
- X
- X end = _F_GETEND(smallman);
- X (void) strcpy(prod,"0");
- X
- X /*
- X ** multiplication by repeated addition
- X */
- X while(end >= smallman)
- X {
- X for(tmp = 0;tmp<*end-'0';tmp++)
- X {
- X _F_stradd(prod,bigman);
- X }
- X addzeros(bigman,1);
- X end--;
- X }
- X
- X R_setfrac(result,prod);
- X R_setexp(result,(((R_getexp(f1) + R_getexp(f2)) - len)+ strlen(prod)));
- X
- X if (R_getsign(f1) == R_getsign(f2))
- X {
- X R_setsign(result,R_POSITIVE);
- X }
- X else
- X {
- X R_setsign(result,R_NEGATIVE);
- X }
- X return(result);
- X}
- X
- X_F_xor(x,y)
- X{
- X return(((x) && !(y)) || (!(x) && (y)));
- X}
- X#define _F_SAMESIGN(x,y) _F_xor((x<0),(y<0))
- X#define _F_ABSADD(x,y) (Z_ABS(x) + Z_ABS(y))
- X
- X_F_ABSDIFF(x,y)
- X{
- X if (Z_ABS(x) < Z_ABS(y))
- X {
- X return(Z_ABS(y) - Z_ABS(x));
- X }
- X else
- X {
- X return(Z_ABS(x) - Z_ABS(y));
- X }
- X}
- X/*
- X** add two floats without regard to sign
- X*/
- XF_float
- XF_floatmagadd(p1,p2)
- XF_float p1,p2;
- X{
- X static F_float result;
- X static int needinit = 1;
- X
- X static char man1[R_MANMAX],man2[R_MANMAX];
- X
- X int digits; /* count of the number of digits needed to represent the
- X result */
- X int resexp; /* exponent of the result */
- X int len; /* length of the elements before adding */
- X char *diffptr;
- X
- X if (needinit)
- X {
- X result = R_makefloat();
- X needinit = 0;
- X }
- X (void) strcpy(man1,"");
- X (void) strcpy(man2,"");
- X
- X /*
- X ** find the difference in the exponents number of digits
- X */
- X if( _F_SAMESIGN(R_getexp(p1),R_getexp(p2)))
- X {
- X digits = _F_ABSDIFF(R_getexp(p1),R_getexp(p2));
- X }
- X else
- X {
- X digits = _F_ABSADD(R_getexp(p1),R_getexp(p2));
- X }
- X
- X /*
- X ** make sure that there is room to store the result
- X */
- X if (digits>0)
- X {
- X if (R_getexp(p1) < R_getexp(p2))
- X {
- X /*
- X ** leave room for terminator
- X */
- X if (digits+strlen(R_getfrac(p1)) > (R_MANMAX-1))
- X {
- X (void) sprintf(Z_err_buf,
- X "numbers differ by too much in magnitude");
- X Z_fatal(Z_err_buf);
- X }
- X }
- X else
- X {
- X /*
- X ** leave room for terminator
- X */
- X if (digits+strlen(R_getfrac(p2)) > (R_MANMAX-1))
- X {
- X (void) sprintf(Z_err_buf,
- X "numbers differ by too much in magnitude");
- X Z_fatal(Z_err_buf);
- X }
- X }
- X }
- X else
- X {
- X /*
- X ** leave room for terminator and possible carry
- X */
- X if (Z_MAX(strlen(R_getfrac(p1)),
- X strlen(R_getfrac(p2))) > (R_MANMAX-2))
- X {
- X (void) sprintf(Z_err_buf,
- X "numbers differ by too much in magnitude");
- X Z_fatal(Z_err_buf);
- X }
- X }
- X
- X /*
- X ** pad zeroes on the front of the smaller number
- X */
- X if (R_getexp(p1) < R_getexp(p2))
- X {
- X
- X addzeros(man1,digits);
- X resexp = R_getexp(p2);
- X }
- X else
- X {
- X addzeros(man2,digits);
- X resexp = R_getexp(p1);
- X }
- X (void) strcat(man1,R_getfrac(p1));
- X (void) strcat(man2,R_getfrac(p2));
- X
- X len = Z_MAX(strlen(man1),strlen(man2));
- X
- X /*
- X ** add the two values
- X */
- X _F_stradd(man1,man2);
- X
- X /*
- X ** adjust the exponent to account for a
- X ** possible carry
- X */
- X resexp += strlen(man1) - len;
- X
- X
- X /*
- X ** trim the leading zeros on the sum
- X */
- X diffptr = man1;
- X while('0' == *diffptr)
- X {
- X diffptr++;
- X resexp--;
- X }
- X
- X R_setfrac(result,diffptr);
- X R_setexp(result,resexp);
- X R_setsign(result,R_POSITIVE);
- X
- X return(result);
- X}
- X
- X/*
- X** useful debugging routine. we don't call it in the release,
- X** so it is commented out, but we'll leave it for future use
- X*/
- X
- X/*
- XF_printfloat(fl)
- XF_float fl;
- X{
- X (void) printf("fraction = :%s: exp = %d sign = %c\n",
- X R_getfrac(fl),
- X R_getexp(fl),
- X ((R_getsign(fl) == R_POSITIVE) ? '+': '-'));
- X
- X}
- X*/
- END_OF_FILE
- if test 13078 -ne `wc -c <'float.c'`; then
- echo shar: \"'float.c'\" unpacked with wrong size!
- fi
- # end of 'float.c'
- fi
- if test -f 'parse.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'parse.c'\"
- else
- echo shar: Extracting \"'parse.c'\" \(16604 characters\)
- sed "s/^X//" >'parse.c' <<'END_OF_FILE'
- X/* Copyright (c) 1988 Bellcore
- X** All Rights Reserved
- X** Permission is granted to copy or use this program, EXCEPT that it
- X** may not be sold for profit, the copyright notice must be reproduced
- X** on copies, and credit should be given to Bellcore where it is due.
- X** BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
- X*/
- X
- X
- X#ifndef lint
- Xstatic char rcsid[]= "$Header: parse.c,v 1.1 88/09/15 11:33:57 daniel Rel $";
- X#endif
- X
- X#include "misc.h"
- X#include "flagdefs.h"
- X#include "float.h"
- X#include "tol.h"
- X#include "token.h"
- X#include "line.h"
- X#include "command.h"
- X#include "comment.h"
- X#include "parse.h"
- X
- X
- X#include <ctype.h>
- X
- X#define _P_PARSE_CHATTER 1000
- X
- X
- Xstatic int _P_realline; /* loop counter */
- Xstatic int _P_fnumb;
- X
- Xstatic char *_P_nextchr; /* pointer to the next character to parse */
- Xstatic char *_P_firstchr; /* pointer to the beginning of the line being parsed */
- Xstatic int _P_next_tol; /* number of floats seen on this line */
- Xstatic int _P_stringsize; /* count of number of characters that are being
- X read into a comment or literal */
- Xstatic int _P_has_content; /* flag to indicate if the line being
- X parsed has any tokens on it */
- Xstatic int _P_start; /* first line to parse */
- Xstatic int _P_lcount; /* number of lines to parse */
- X
- Xstatic int _P_flags; /* location for global flags */
- X
- X/*
- X** by default, "words" can be made up of numbers and letters
- X** the following code allows for extending the alphabet that can
- X** be used in words. this is useful for handling languages such
- X** as C where the underscore character is an allowable character
- X** in an identifier. If a character (such as underscore) is NOT added
- X** to the alphabet, the identifier will be broken into 2 or more "words"
- X** by the parser. as such the two sequences
- X** one_two
- X** and
- X** one _ two
- X** would look identical to spiff.
- X*/
- X#define _P_ALPHALEN 256
- Xstatic char _P_alpha[_P_ALPHALEN];
- X
- Xstatic void
- X_P_alpha_clear()
- X{
- X *_P_alpha = '\0';
- X}
- X
- Xstatic
- X_P_in_alpha(chr)
- Xchar chr;
- X{
- X#ifndef ATT
- X extern int index();
- X#endif
- X /*
- X ** special case when string terminator
- X ** is handed to us
- X */
- X if ('\0' == chr)
- X return(0);
- X
- X#ifdef ATT
- X return((int) strchr(_P_alpha,chr));
- X#else
- X return((int) index(_P_alpha,chr));
- X#endif
- X}
- X
- Xvoid
- XP_addalpha(ptr)
- Xchar *ptr;
- X{
- X char buf[Z_LINELEN];
- X
- X S_wordcpy(buf,ptr); /* copy up to (but not including)
- X the first whitespace char */
- X
- X if ((strlen(_P_alpha) + strlen(buf)) >= _P_ALPHALEN)
- X {
- X Z_fatal("too many characters added to extended alphabet");
- X }
- X (void) strcat(_P_alpha,buf);
- X}
- X
- X/*
- X** put parser in a default state
- X*/
- X
- Xstatic char _P_dummyline[2]; /* a place to aim wild pointers */
- Xstatic void
- X_P_initparser()
- X{
- X _P_dummyline[0] = '\0';
- X
- X /*
- X ** now reset all the state of each module
- X */
- X C_clear_cmd(); /* disable embedded command key word */
- X T_clear_tols();
- X W_clearcoms();
- X W_clearlits();
- X _P_alpha_clear(); /* disable extended alphabet */
- X
- X /*
- X ** and set state as defined by execute-time commands.
- X */
- X C_docmds();
- X return;
- X}
- X
- X
- Xstatic
- X_P_needmore()
- X{
- X return(*_P_nextchr == '\0');
- X}
- X
- Xstatic
- X_P_nextline()
- X{
- X /*
- X ** if the line that we just finished had
- X ** some content, increment the count
- X */
- X if (_P_has_content)
- X {
- X L_incclmax(_P_fnumb);
- X /*
- X ** if the previous line had a token
- X ** increment the line
- X */
- X if (L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
- X {
- X L_inctlmax(_P_fnumb);
- X L_setcount(_P_fnumb,L_gettlmax(_P_fnumb),0);
- X }
- X _P_has_content = 0;
- X }
- X
- X /*
- X ** reset the number of floats seen on the line
- X */
- X _P_next_tol = 0;
- X
- X /*
- X ** get another line if there is one available
- X */
- X _P_realline++;
- X if (_P_realline >= _P_start+_P_lcount)
- X {
- X return(1);
- X }
- X
- X _P_firstchr = _P_nextchr = L_getrline(_P_fnumb,_P_realline);
- X /*
- X ** and look for a command
- X */
- X if (C_is_cmd(_P_firstchr))
- X {
- X _P_nextchr = _P_dummyline;
- X _P_has_content = 0;
- X }
- X else
- X {
- X /*
- X ** we have a real line, so set up the index
- X */
- X L_setclindex(_P_fnumb,L_getclmax(_P_fnumb),_P_realline);
- X _P_has_content = 1;
- X }
- X return(0);
- X}
- X
- X/*
- X** the following three routines (_P_litsnarf, _P_bolsnarf, and _P_comsnarf
- X** all do roughly the same thing. they scan ahead and collect the
- X** specified string, move _P_nextchr to the end of the
- X** comment or literal and return 1 if we run off the end of file,
- X** 0 otherwise. it would have been nice to have 1 routine handle
- X** all three task (there is much common code), however there were
- X** so enough differences, (for instance, only comments check for nesting,
- X** only literals need to set _P_stringsize, etc)
- X** that I decided to split them up.
- X*/
- Xstatic int
- X_P_litsnarf(litptr)
- XW_lit litptr;
- X{
- X _P_stringsize = 0;
- X /*
- X ** skip the start of literal string
- X */
- X _P_nextchr += strlen(W_litbegin(litptr));
- X _P_stringsize += strlen(W_litbegin(litptr));
- X /*
- X ** is there a separate end string?
- X ** if not, then we're done
- X */
- X if ('\0' == *(W_litend(litptr)))
- X {
- X return(0);
- X }
- X /*
- X ** loop once for each character in the literal
- X */
- X while(1)
- X {
- X /*
- X ** if we are out of characters, move on to next line
- X */
- X if (_P_needmore())
- X {
- X if (_P_nextline())
- X {
- X return(1);
- X }
- X if (!_P_has_content)
- X {
- X /*
- X ** since we've just gotten a command
- X ** check to see if this literal
- X ** is still legit ...
- X ** could have just been reset
- X ** by the command
- X */
- X if (!W_is_lit(litptr))
- X {
- X return(0);
- X }
- X }
- X } /* if _P_needmore */
- X
- X /*
- X ** see if we have an escaped end of literal string
- X */
- X if (('\0' != *(W_litescape(litptr))) && /* escape string exists */
- X !S_wordcmp(_P_nextchr,
- X W_litescape(litptr)) && /* and escape matches */
- X !S_wordcmp(_P_nextchr+strlen(W_litescape(litptr)),
- X W_litend(litptr))) /* and endstring matches */
- X {
- X _P_nextchr += strlen(W_litescape(litptr))
- X + strlen(W_litend(litptr));
- X _P_stringsize += strlen(W_litescape(litptr))
- X + strlen(W_litend(litptr));
- X continue;
- X }
- X
- X /*
- X ** see if we have an end of literal string
- X */
- X if (!S_wordcmp(_P_nextchr,W_litend(litptr))) /* escape matches */
- X {
- X _P_nextchr += strlen(W_litend(litptr));
- X _P_stringsize += strlen(W_litend(litptr));
- X return(0);
- X }
- X /*
- X ** this must be yet another character in the literal, so
- X ** just snarf it up
- X */
- X _P_nextchr++;
- X _P_stringsize++;
- X } /* while loop once for each character */
- X
- X#ifndef lint
- X Z_fatal("shouldn't execute this line at the end of _P_litsnarf");
- X#endif
- X} /* _P_litsnarf */
- X
- Xstatic int
- X_P_bolsnarf(bolptr)
- XW_bol bolptr;
- X{
- X /*
- X ** skip the start of comment string
- X */
- X _P_nextchr += strlen(W_bolbegin(bolptr));
- X /*
- X ** is there a separate end string
- X ** if not, then we're done
- X */
- X if ('\0' == *(W_bolend(bolptr)))
- X {
- X return(0);
- X }
- X /*
- X ** loop once for each character in the comment
- X */
- X while(1)
- X {
- X /*
- X ** if we are out of characters,move on to next line
- X */
- X if (_P_needmore())
- X {
- X if (_P_nextline())
- X {
- X return(1);
- X }
- X if (!_P_has_content)
- X {
- X /*
- X ** since we've just gotten a command
- X ** check to see if this comment
- X ** is still legit ... comments
- X ** could have just been reset
- X ** by the command
- X */
- X if (!W_is_bol(bolptr))
- X {
- X return(0);
- X }
- X }
- X } /* if at end of line */
- X
- X /*
- X ** see if we have an escaped end of comment string
- X */
- X if ('\0' != *(W_bolescape(bolptr)) && /* escape string exists */
- X !S_wordcmp(_P_nextchr,
- X W_bolescape(bolptr)) && /* and escape matches */
- X !S_wordcmp(_P_nextchr+strlen(W_bolescape(bolptr)),
- X W_bolend(bolptr))) /* and end string matches */
- X {
- X _P_nextchr += strlen(W_bolescape(bolptr))
- X + strlen(W_bolend(bolptr));
- X continue;
- X }
- X
- X /*
- X ** see if we have an end of comment string
- X */
- X if (!S_wordcmp(_P_nextchr,W_bolend(bolptr)))
- X {
- X _P_nextchr += strlen(W_bolend(bolptr));
- X return(0);
- X }
- X /*
- X ** this must be yet another character in the comment, so
- X ** just snarf it up
- X */
- X _P_nextchr++;
- X } /* while loop once for each character */
- X
- X#ifndef lint
- X Z_fatal("shouldn't execute this line in at end of _P_bolsnarf");
- X#endif
- X} /* _P_bolsnarf */
- X
- X/*
- X** pass over a comment -- look for nexting
- X*/
- Xstatic
- X_P_comsnarf(comptr)
- XW_com comptr;
- X{
- X int depth = 1; /* nesting depth */
- X /*
- X ** skip the start of comment string
- X */
- X _P_nextchr += strlen(W_combegin(comptr));
- X
- X /*
- X ** is there a separate end string
- X ** if not, then we're done
- X */
- X if ('\0' == *(W_comend(comptr)))
- X {
- X return(0);
- X }
- X /*
- X ** loop once for each character in the comment
- X */
- X while(1)
- X {
- X /*
- X ** if we are out of characters, move on to next line
- X */
- X if (_P_needmore())
- X {
- X if (_P_nextline())
- X {
- X return(1);
- X }
- X if (!_P_has_content)
- X {
- X /*
- X ** since we've just gotten a command
- X ** check to see if this comment
- X ** is still legit ... comments
- X ** could have just been reset
- X ** by the command
- X */
- X if (!W_is_com(comptr))
- X {
- X return(0);
- X }
- X }
- X } /* if at end of line */
- X
- X /*
- X ** see if we have an escaped end of comment string
- X */
- X if ('\0' != *(W_comescape(comptr)) && /* escape string exists */
- X !S_wordcmp(_P_nextchr,
- X W_comescape(comptr)) && /* and escape matches */
- X !S_wordcmp(_P_nextchr+strlen(W_comescape(comptr)),
- X W_comend(comptr))) /* and end string matches */
- X {
- X /*
- X ** skip over the escape sequence and the end sequence
- X */
- X _P_nextchr += strlen(W_comescape(comptr))
- X + strlen(W_comend(comptr));
- X continue;
- X }
- X
- X /*
- X ** see if we have an end of comment string
- X */
- X if (!S_wordcmp(_P_nextchr,W_comend(comptr))) /* end matches */
- X {
- X /*
- X ** skip over the end sequence
- X */
- X _P_nextchr += strlen(W_comend(comptr));
- X if (W_is_nesting(comptr))
- X {
- X depth--;
- X if (0 == depth)
- X return(0);
- X }
- X else
- X {
- X return(0);
- X }
- X continue;
- X }
- X /*
- X ** see if we have another beginning of comment string
- X */
- X if (W_is_nesting(comptr) &&
- X !S_wordcmp(_P_nextchr,W_comend(comptr))) /* end matches */
- X {
- X _P_nextchr += strlen(W_comend(comptr));
- X depth++;
- X continue;
- X }
- X /*
- X ** this must be yet another character in the comment, so
- X ** just snarf it up
- X */
- X _P_nextchr++;
- X } /* while loop once for each character */
- X
- X#ifndef lint
- X Z_fatal("should not execute this line in _P_comsnarf\n");
- X#endif
- X
- X} /* _P_comsnarf */
- X
- X
- X/*
- X** parse a file
- X*/
- Xstatic void
- X_P_do_parse()
- X{
- X
- X char *ptr; /* scratch space */
- X int tmp;
- X int ret_code;
- X
- X K_token newtoken;
- X W_bol bolptr;
- X W_com comptr;
- X W_lit litptr;
- X
- X int startline, endline, startpos;
- X
- X /*
- X ** main parsing loop
- X */
- X while (1)
- X {
- X /*
- X ** get more text if necessary
- X */
- X if (_P_needmore())
- X {
- X if (_P_nextline())
- X {
- X return;
- X }
- X
- X /*
- X ** if the line contains nothing of interest,
- X ** try again
- X */
- X if (!_P_has_content)
- X {
- X continue;
- X }
- X
- X /*
- X ** check to see if this line starts a comment
- X */
- X if ((bolptr = W_isbol(_P_firstchr)) != W_BOLNULL)
- X {
- X if (_P_bolsnarf(bolptr))
- X {
- X return;
- X }
- X continue;
- X }
- X } /* if _P_needmore */
- X
- X /*
- X ** skip whitespace
- X */
- X if (!(U_INCLUDE_WS & _P_flags) && isspace(*_P_nextchr))
- X {
- X _P_nextchr++;
- X continue;
- X }
- X
- X /*
- X ** check to see if this character starts a comment
- X */
- X if ((comptr = W_iscom(_P_nextchr)) != W_COMNULL)
- X {
- X if (_P_comsnarf(comptr))
- X {
- X return;
- X }
- X continue;
- X }
- X
- X /*
- X ** if there aren't any tokens on this line already
- X ** set up the index from the token line to the content line
- X */
- X if (!L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
- X {
- X L_settlindex(_P_fnumb,
- X L_gettlmax(_P_fnumb),
- X L_getclmax(_P_fnumb));
- X /*
- X ** and the pointer from the token line to the
- X ** first token on the line
- X */
- X L_setindex(_P_fnumb,
- X L_gettlmax(_P_fnumb),
- X K_gettmax(_P_fnumb));
- X }
- X
- X startline = L_tl2cl(_P_fnumb,L_gettlmax(_P_fnumb));
- X startpos = _P_nextchr-_P_firstchr;
- X
- X newtoken = K_maketoken();
- X K_setline(newtoken,L_gettlmax(_P_fnumb));
- X K_setpos(newtoken,startpos);
- X
- X ret_code = 0;
- X /*
- X ** check to see if this character starts a
- X ** delimited literal string
- X */
- X if ((litptr = W_islit(_P_nextchr)) != W_LITNULL)
- X {
- X ret_code = _P_litsnarf(litptr);
- X K_settype(newtoken,K_LIT);
- X S_allocstr(&ptr,_P_stringsize);
- X /*
- X ** fixed nasty memory bug here by adding else
- X ** old code copied entire line even if literal
- X ** ended before the end of line
- X ** should check into getting strcpy loaded
- X ** locally
- X */
- X endline = L_getclmax(_P_fnumb);
- X if (endline > startline)
- X {
- X /*
- X ** copy in the first line of the literal
- X */
- X (void) strcpy(ptr,
- X L_getcline(_P_fnumb,startline)
- X +startpos);
- X /*
- X ** now copy all the lines between
- X ** the first and last
- X */
- X for (tmp=startline+1;tmp<endline;tmp++)
- X {
- X (void) strcat(ptr,
- X L_getcline(_P_fnumb,tmp));
- X }
- X /*
- X ** and now copy in the last line
- X */
- X (void) strncat(ptr,
- X L_getcline(_P_fnumb,endline),
- X _P_stringsize-strlen(ptr));
- X }
- X else
- X {
- X (void) strncpy(ptr,
- X L_getcline(_P_fnumb,startline)
- X +startpos,
- X _P_stringsize);
- X /*
- X ** terminate the string you just copied
- X */
- X ptr[_P_stringsize] = '\0';
- X }
- X K_settext(newtoken,ptr);
- X } /* if is_lit */
- X
- X /*
- X ** see if this is a floating point number
- X */
- X else if (tmp = F_isfloat(_P_nextchr,
- X _P_flags & U_NEED_DECIMAL,
- X _P_flags & U_INC_SIGN))
- X {
- X K_saventext(newtoken,_P_nextchr,tmp);
- X K_settype(newtoken,K_FLO_NUM);
- X if (!(_P_flags & U_BYTE_COMPARE))
- X {
- X K_setfloat(newtoken,
- X F_atof(K_gettext(newtoken),
- X USE_ALL));
- X
- X /*
- X ** assign the curent tolerance
- X */
- X K_settol(newtoken,T_gettol(_P_next_tol));
- X }
- X
- X /*
- X ** use next tolerance in the
- X ** specification if there is one
- X */
- X if (T_moretols(_P_next_tol))
- X {
- X _P_next_tol++;
- X }
- X /*
- X ** and move pointer past the float
- X */
- X _P_nextchr += tmp;
- X }
- X
- X /*
- X ** is this a fixed point number
- X */
- X else if (isdigit(*_P_nextchr))
- X {
- X for(ptr=_P_nextchr; isdigit(*ptr); ptr++)
- X {
- X }
- X K_saventext(newtoken,_P_nextchr,ptr-_P_nextchr);
- X K_settype(newtoken,K_LIT);
- X _P_nextchr = ptr;
- X }
- X
- X /*
- X ** try an alpha-numeric word
- X */
- X else if (isalpha(*_P_nextchr) || _P_in_alpha(*_P_nextchr))
- X {
- X /*
- X ** it's a multi character word
- X */
- X for(ptr = _P_nextchr;
- X isalpha(*ptr)
- X || isdigit(*ptr)
- X || _P_in_alpha(*ptr);
- X ptr++)
- X {
- X }
- X K_saventext(newtoken,_P_nextchr,ptr-_P_nextchr);
- X K_settype(newtoken,K_LIT);
- X _P_nextchr = ptr;
- X }
- X else
- X {
- X /*
- X ** otherwise, treat the char itself as a token
- X */
- X K_saventext(newtoken,_P_nextchr,1);
- X K_settype(newtoken,K_LIT);
- X _P_nextchr++;
- X }
- X
- X K_settoken(_P_fnumb,K_gettmax(_P_fnumb),newtoken);
- X L_inccount(_P_fnumb,L_gettlmax(_P_fnumb));
- X /*
- X ** if we are out of space, complain and quit
- X */
- X if (K_inctmax(_P_fnumb))
- X {
- X (void) sprintf(Z_err_buf,
- X "warning -- to many tokens in file only first %d tokens will be used.\n",
- X K_MAXTOKENS);
- X Z_complain(Z_err_buf);
- X return;
- X }
- X#ifndef NOCHATTER
- X if (0 == (K_gettmax(_P_fnumb) % _P_PARSE_CHATTER))
- X {
- X int max = K_gettmax(_P_fnumb);
- X (void) sprintf(Z_err_buf,
- X "scanned %d words from file #%d\n",
- X max,_P_fnumb+1);
- X Z_chatter(Z_err_buf);
- X }
- X#endif
- X
- X /*
- X ** are we done?
- X */
- X if(ret_code)
- X {
- X return;
- X }
- X } /* loop once per object on a line */
- X
- X#ifndef lint
- X Z_fatal("this line should never execute");
- X#endif
- X}
- X
- Xvoid
- XP_file_parse(num,strt,lcnt,flags)
- Xint num; /* file number */
- Xint strt; /* first line to parse expressed in real line numbers */
- Xint lcnt; /* max number of lines to parse */
- Xint flags; /* flags for controlling the parse mode */
- X{
- X /*
- X ** set module-wide state variables
- X */
- X _P_fnumb = num;
- X _P_start = strt;
- X _P_lcount = lcnt;
- X _P_flags = flags;
- X
- X _P_initparser();
- X
- X _P_nextchr = _P_dummyline;
- X
- X _P_has_content = 0;
- X _P_next_tol = 0;
- X L_setcount(_P_fnumb,L_gettlmax(_P_fnumb),0);
- X /*
- X ** start everything back one line (it will be incremented
- X ** just before the first line is accessed
- X */
- X _P_realline = _P_start-1;
- X
- X _P_do_parse();
- X
- X /*
- X ** if the last line had content, increment the count
- X */
- X if (_P_has_content)
- X {
- X/*
- X** this code will get executed if we stopped parsing in the middle
- X** of a line. i haven't looked at this case carefully.
- X** so, there is a good chance that it is buggy.
- X*/
- X(void) sprintf(Z_err_buf,"parser got confused at end of file\n");
- XZ_complain(Z_err_buf);
- X L_incclmax(_P_fnumb);
- X if (L_getcount(_P_fnumb,L_gettlmax(_P_fnumb)))
- X L_inctlmax(_P_fnumb);
- X }
- X return;
- X}
- END_OF_FILE
- if test 16604 -ne `wc -c <'parse.c'`; then
- echo shar: \"'parse.c'\" unpacked with wrong size!
- fi
- # end of 'parse.c'
- fi
- if test -f 'spiff.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'spiff.1'\"
- else
- echo shar: Extracting \"'spiff.1'\" \(14738 characters\)
- sed "s/^X//" >'spiff.1' <<'END_OF_FILE'
- X.ll 6i
- X.pl 10.5i
- X.po 1.25i
- X.\" @(#)spiff.1 1.0 (Bellcore) 9/20/87
- X.\"
- X.lt 6.0i
- X.TH SPIFF 1 "February 2, 1988"
- X.AT 3
- X.SH NAME
- Xspiff \- make controlled approximate comparisons between files
- X.SH SYNOPSIS
- X.B spiff
- X[
- X.B \-s
- Xscript ] [
- X.B \-f
- Xsfile ] [
- X.B \-bteviqcdwm
- X] [
- X.B \-a
- X\(br
- X.B \-r
- Xvalue ] \-value file1 file2
- X.SH DESCRIPTION
- X.I Spiff
- Xcompares the contents of
- X.B file1
- Xand
- X.B file2
- Xand prints a description of the important differences between
- Xthe files.
- XWhite space is ignored except to separate other objects.
- X.I Spiff
- Xmaintains tolerances below which differences between two floating point
- Xnumbers are ignored.
- XDifferences in floating point notation (such as 3.4 3.40 and 3.4e01)
- Xare treated as unimportant.
- XUser specified delimited strings (i.e. comments) can also be ignored.
- XInside other user specified delimited strings
- X(i.e. quoted strings) whitespace can be significant.
- X.PP
- X.I Spiff's
- Xoperation can be altered via command line options, a command script, and with
- Xcommands that are embedded in the input files.
- X.PP
- XThe following options affect
- X.I spiff's
- Xoverall operation.
- X.TP
- X.B \-q
- Xsuppresses warning messages.
- X.TP
- X.B \-v
- Xuse a visually oriented display. Works only in MGR windows.
- X.PP
- X.I Spiff
- Xhas several flags to aid differencing of various programming languages.
- XSee EXAMPLES for a detailed description of the effects of these flags.
- X.TP
- X.B \-C
- Xtreat the input files as C program source code.
- X.TP
- X.B \-S
- Xtreat the input files as Bourne shell program source code.
- X.TP
- X.B \-F
- Xtreat the input files as Fortran program source code.
- X.TP
- X.B \-M
- Xtreat the input files as Modula-2 program source code.
- X.TP
- X.B \-L
- Xtreat the input files as Lisp program source code.
- X.PP
- XBy default, the output looks somewhat similar in appearance
- Xto the output of diff(1). Lines with differences are printed with
- Xthe differences highlighted. If stdout is a terminal, as determined
- Xby isatty(), then highlighting uses standout mode as determined by termcap.
- XIf stdout is not a tty, then the underlining (via underscore/backspace/char)
- Xis used to highlight differences.
- XThe following option can control the format of the ouput.
- X.TP
- X.B \-t
- Xproduce output in terms of individual tokens. This option is
- Xmost useful for debugging as the output produced is verbose to
- Xthe point of being unreadable.
- X.PP
- XThe following option controls the differencing algorithm.
- X.TP
- X.B \-e
- Xcompare each token
- Xin the files with the object in the same ordinal
- Xposition in the other file. If the files have a different number
- Xof objects, a warning message is printed
- Xand the objects at the end of the longer file are ignored.
- XBy default,
- X.I spiff
- Xuses a Miller/Myers algorithm to find a minimal edit sequence
- Xthat will convert the contents of the first file into the second.
- X.TP
- X\-<decimal-value>
- Xsets a limit on the total number of insertions and deletions
- Xthat will be considered.
- XIf the files differ by more than the stated amount,
- Xthe program will give up, print a warning message, and exit.
- X.PP
- XThe following options control the command script. More than one of
- Xeach may appear at at time. The commands accumulate.
- X.TP
- X.B \-f sfile
- Xa command script to be taken from file
- X.IR sfile
- X.TP
- X.B \-s command-script
- Xcauses the following argument to be taken as a command script.
- X.PP
- XThe following options control how individual objects are compared.
- X.TP
- X.B \-b
- Xtreat all objects (including floating point numbers) as literals.
- X.TP
- X.B \-c
- Xignore differences between upper and lower case.
- X.PP
- XThe following commands will control how the files are parsed.
- X.TP
- X.B \-w
- Xtreat white space as objects. Each white space character will
- Xbe treated as a separate object when the program is comparing the
- Xfiles.
- X.TP
- X.B \-m
- Xtreat leading sign characters ( + and \- ) as separate even
- Xif they are followed by floating point numbers.
- X.TP
- X.B \-d
- Xtreat integer decimal numbers (such as 1987) as real numbers (subject to
- Xtolerances) rather than as literal strings.
- X.PP
- XThe following three flags are used to set the default tolerances.
- XThe floating-point-numbers may be given in the formats accepted
- Xby atof(3).
- X.TP
- X.B \-a floating-point-number
- Xspecifies an absolute value for the tolerance in floating point numbers.
- XThe flag
- X.B \-a1e-2
- Xwill cause all differences greater than 0.01 to be reported.
- X.TP
- X.B \-r floating-point-number
- Xspecifies a relative tolerance. The value given is interpreted
- Xas a fraction of the larger (in absolute terms)
- Xof the two floating point numbers being compared.
- XThus, the flag
- X.B \-r0.1
- Xwill cause the two floating point numbers 1.0 and 0.9 to be deemed within
- Xtolerance. The numbers 1.0 and 0.89 will be outside the tolerance.
- X.TP
- X.B \-i
- Xcauses differences between floating point numbers to be ignored.
- X.PP
- XIf more than one
- X.B \-a, \-r,
- Xor
- X.B \-i
- Xflag appear on the command line,
- Xthe tolerances will be OR'd together (i.e. any difference that is within
- Xany of the tolerances will be ignored).
- X.PP
- XIf no default tolerances is set on the command line,
- Xthe program will use a default tolerance of
- X.B '\-a 1e-10 \-r 1e-10'.
- X.SH SCRIPT COMMANDS
- X.PP
- XA script consists of commands, one per line.
- XEach command consists of a keyword possibly followed by arguments.
- XArguments are separated by one or more tabs or spaces.
- XThe commands are:
- X.TP
- Xliteral BEGIN-STRING [END-STRING [ESCAPE-STRING]]
- XSpecifies the delimiters surrounding text that is to be treated as a single
- Xliteral object. If only one argument is present, then only that string itself is treated
- Xas a literal. If only two arguments are present, they are taking as the starting
- Xand ending delimiters respectively. If three arguments are present, they are treated
- Xas the start delimiter, end delimiter, and a string that may be used to escape
- Xan instance of the end delimiter.
- X.TP
- Xbeginchar BEGINNING-OF-LINE-CHARACTER
- XSet the the beginning of line character for BEGIN-STRING's in comments.
- XThe default is '^'.
- X.TP
- Xendchar END-OF-LINE-CHARACTER
- XSet the end of line character for END-STRING's in comments.
- XThe default is '$'.
- X.TP
- Xaddalpha NEW-ALPHA-CHARACTER
- XAdd NEW-ALPHA-CHARACTER to the set of characters allowed in literal strings.
- XBy default,
- X.I spiff
- Xparses sequences of characters that begin with a letter and followed by
- Xzero or more letters or numbers as a single literal token. This definition
- Xis overly restrictive when dealing with programming languages.
- XFor example, in the C programming language,
- Xthe underscore character is allowed in identifiers.
- X.TP
- Xcomment BEGIN-STRING [END-STRING [ESCAPE-STRING]]
- XSpecifies the delimiters surrounding text that is to be be ignored entirely
- X(i.e. viewed as comments).
- XThe operation of the comment command is very similar to the literal command.
- XIn addition, if the END-STRING consists of only
- Xthe end of line character, the end of line will delimit the end of the comment.
- XAlso, if the BEGIN-STRING starts with the beginning of line character, only
- Xlines that begin with the BEGIN-STRING will be ignored.
- X.PP
- XMore than one comment specification and more than one literal string specification
- Xmay be specified at a time.
- X.TP
- Xnestcom BEGIN-STRING [END-STRING [ESCAPE-STRING]]
- XSimilar to the comment command, but allows comments to be nested.
- XNote, due to the design of the parser nested comments can not
- Xhave a BEGIN-STRING that starts with the beginning of line character.
- X.TP
- Xresetcomments
- XClears the list of comment specifications.
- X.TP
- Xresetliterals
- XClears the list of literal specifications.
- X.TP
- Xtol [aVALUE\(brrVALUE\(bri\(brd . . . [ ; aVALUE\(brrVALUE\(bri\(brd . . . ] . . . ]
- Xset the tolerance for floating point comparisons.
- XThe arguments to the tol command are a set of tolerance specifications
- Xseparated by semicolons. If more than one a,r,d, or i appears within
- Xa specification, then the tolerances are OR'd together (i.e. any difference
- Xthat is within any tolerance will be ignored).
- XThe semantics of a,r, and i are identical to the
- X.B \-a, \-r,
- Xand
- X.B \-i
- Xflags. The d means that the default tolerance (as specified by the invocation
- Xoptions) should be used.
- XIf more than one specification appears on the line, the first
- Xspecification is applied to the first floating point number on each line,
- Xthe second specification to the second floating point number one each line
- Xof the input files, and so on. If there are more floating point numbers
- Xon a given line of input than tolerance specifications,
- Xthe last specification is used repeatedly for all remaining floating point numbers
- Xon that line.
- X.TP
- Xcommand STRING
- Xlines in the input file that start with STRING will be interpreted as
- Xcommand lines. If no "command" is given as part of a
- X.B \-s
- Xor
- X.B \-f
- Xthen it will be impossible to embed commands in the input files.
- X.TP
- Xrem
- X.TP
- X#
- Xused to places human readable remarks into a commands script. Note that the
- Xuse of the '#' character differs from other command languages (for instance
- Xthe Bourne shell).
- X.I Spiff
- Xwill only recognize the '#' as beginning a comment when it is the first
- Xnon-blank character on the command line. A '#' character appearing elsewhere
- Xwill be treated as part of the command. Cautious users should use 'rem'.
- XThose hopelessly addicted to '#' as a comment character can have command
- Xscripts with a familiar format.
- X.PP
- XTolerances specified in the command scripts have precedence over the tolerance
- Xspecified on the invocation command line. The tolerance specified in
- X.I file1
- Xhas precedence over the tolerance specified in
- X.I file2.
- X.PP
- X.SH VISUAL MODE
- XIf
- X.I spiff
- Xis invoked with the \-v option, it will enter an interactive mode rather
- Xthan produce an edit sequence. Three windows will be put on the screen.
- XTwo windows will contain corresponding segments of the input files.
- XObjects that appear in both segments will be examined for differences and
- Xif any difference is found, the objects will be highlighted in reverse video
- Xon the screen. Objects that appear in only one window will have a line drawn
- Xthrough them to indicate that they aren't being compared with anything in the other
- Xtext window. The third window is a command window. The command window will
- Xaccept a single tolerance specification (followed by a newline)
- Xin a form suitable to the
- X.B tol
- Xcommand. The tolerance specified will then be used as the default tolerance
- Xand the display will be updated to highlight only those objects that exceed
- Xthe new default tolerance. Typing
- X.B m
- X(followed by a newline) will display the next screenfull of text. Typing
- X.B q
- X(followed by a newline) will cause the program to exit.
- X.SH LIMITS
- XEach input files can be no longer that 10,000 line long or contain more
- Xthan 50,000 tokens. Longer files will be truncated.
- XNo line can be longer than 1024 characters. Newlines
- Xwill be inserted every 1024 character.
- X.SH EXAMPLES
- X.TP
- Xspiff \-e \-d foo bar
- Xthis invocation (using exact match algorithm and treating integer numbers
- Xas if they were floats) is very useful for examining large tables of numbers.
- X.TP
- Xspiff \-0 foo bar
- Xcompare the two files, quitting after the first difference is found.
- XThis makes the program operate roughly like cmp(1).
- X.TP
- Xspiff \-0 -q foo bar
- Xsame as the above, but no output is produced.
- XThe return code is still useful.
- X.TP
- Xspiff \-w \-b foo bar
- Xwill make the program operate much like diff(1).
- X.TP
- Xspiff \-a1e-5 \-r0.001 foo bar
- Xcompare the contents of the files foo and bar and ignore all differences between
- Xfloating point numbers that are less than or equal to
- X0.00001 or 0.1% of the number of larger magnitude.
- X.TP
- Xtol a.01 r.01
- Xwill cause all differences between floating point numbers that are less than
- Xor equal to
- X0.01 or 1% of the number of larger magnitude to be ignored.
- X.TP
- Xtol a.01 r.01 ; i
- Xwill cause the tolerance in the previous example to be applied to the first
- Xfloating point number on each line. All differences between the second and
- Xsubsequent floating point numbers on each line will be ignored.
- X.TP
- Xtol a.01 r.01 ; i ; a.0001
- Xlike the above except that only differences between the second floating point
- Xnumber on each line will be ignored. The differences between
- Xthird and subsequent floating point numbers on each number will be ignored if they
- Xare less than or equal to 0.0001.
- X.IP
- XA useful script for examing C code is:
- X.nf
- Xliteral " " \\
- Xcomment /* */
- Xliteral &&
- Xliteral \(br\(br
- Xliteral <=
- Xliteral >=
- Xliteral !=
- Xliteral ==
- Xliteral --
- Xliteral ++
- Xliteral <<
- Xliteral >>
- Xliteral ->
- Xaddalpha _
- Xtol a0
- X.fi
- X.IP
- XA useful script for shell programs is:
- X.nf
- Xliteral ' ' \\
- Xcomment # $
- Xtol a0
- X.fi
- X.IP
- XA useful script for Fortran programs is:
- X.nf
- Xliteral ' ' '
- Xcomment ^C $
- Xtol a0
- X.fi
- X.IP
- XA useful script for Modula 2 programs is:
- X.nf
- Xliteral ' '
- Xliteral " "
- Xnestcom (* *)
- Xliteral :=
- Xliteral <>
- Xliteral <=
- Xliteral >=
- Xtol a0
- X.fi
- X.IP
- XA useful script for Lisp programs is:
- X.nf
- Xliteral " "
- Xcomment ; $
- Xtol a0
- X.fi
- X.SH DIAGNOSTICS
- X.I Spiff's
- Xexit status is 0 if no differences are found, 1 if differences are found, and
- X2 upon error.
- X.SH BUGS
- XIn C code, escaped newlines will appear as differences.
- X.PP
- XComments are treated as token delimiters.
- X.PP
- XComments in Basic don't work right. The line number is not ignored.
- X.PP
- XContinuation lines in Fortran comments don't work.
- X.PP
- XThere is no way to represent strings specified using a
- XHollerith notation in Fortran.
- X.PP
- XIn formated English text, hyphenated words,
- Xmovements in pictures, footnotes, etc.
- Xwill be reported as differences.
- X.PP
- XSTRING's in script commands can not include whitespace.
- X.PP
- XVisual mode does not handle tabs properly. Files containing
- Xtabs should be run through
- Xexpand(1) before trying to display them with visual mode.
- X.PP
- XIn visual mode, the text windows appear in a fixed size and font.
- XLines longer than the window size will not be handled properly.
- X.PP
- XObjects (literal strings) that contain newlines cause trouble in several places
- Xin visual mode.
- X.PP
- XVisual mode should accept more than one tolerance specification.
- X.PP
- XWhen using visual mode or the exact match comparison algorithm, the program
- Xshould do the parsing on the fly rather than truncating long files.
- X.SH AUTHOR
- XDaniel Nachbar
- X.SH COPYRIGHT
- X.nf
- X Copyright (c) 1988 Bellcore
- X All Rights Reserved
- XPermission is granted to copy or use this program,
- XEXCEPT that it may not be sold for profit, the copyright
- Xnotice must be reproduced on copies, and credit should
- Xbe given to Bellcore where it is due.
- X BELLCORE MAKES NO WARRANTY AND ACCEPTS
- X NO LIABILITY FOR THIS PROGRAM.
- X.fi
- X
- X.br
- X.SH SEE ALSO
- Xatof(3)
- Xisatty(2)
- Xdiff(1)
- Xcmp(1)
- Xexpand(1)
- Xmgr(1L)
- X.PP
- X"Spiff -- A Program for Making Controlled Approximate Comparisons of Files",
- Xby Daniel Nachbar.
- X.PP
- X"A File Comparison Program" by Webb Miller and Eugene W. Myers in Software \-
- XPractice and Experience, Volume 15(11), pp.1025-1040, (November 1985).
- END_OF_FILE
- if test 14738 -ne `wc -c <'spiff.1'`; then
- echo shar: \"'spiff.1'\" unpacked with wrong size!
- fi
- # end of 'spiff.1'
- fi
- echo shar: End of archive 3 \(of 4\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 4 archives.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-